<?php

/**
 * Glossary
 * @author SilverBiology
 * @link http://www.silverbiology.com
 */

include_once('class.mysqli_database.php');

Class Glossary 
{
	public $genus, $species, $author;

	public function __construct() {

		global $mysql_host, $mysql_db, $mysql_user, $mysql_pass;
		$this->connection_string = sprintf("server=%s; database=%s; username=%s; password=%s; charset=UTF8;"
			,	$mysql_host
			, $mysql_db
			,	$mysql_user
			,	$mysql_pass
		);

		$this->db = new MysqliDatabase( $this->connection_string);
		$this->db->query_all('SET CHARACTER SET UTF8');
	}
	
	public function getList( $type, $value = NULL ) {
		switch ($type) {
			default:
			case 'root':
				return( $this->getRoot() );
				break;

			case 'alpha':
				return( $this->getAlpha() );
				break;

			case 'letter':
				return( $this->getLetter( $value ) );
				break;

			case 'codeStatus':
				return( $this->getCodeStatus() );
				break;

			case 'termType':
				return( $this->getTermType() );
				break;

			case 'code':
				return( $this->getCode() );
				break;
		}
	}
	
	public function search() {
	}
	
	public function getDefinitionsByLetter( $value, $hyperlink = 1 ) {
#		$codes = $this->getCodeStatus();
#		$codes = $this->getCode();
		if ($value == "#") {
			$query = "SELECT d.recordID, d.definition, d.sequence, d.code, d.codeStatus, t.termID, t.term, t.termStatus, t.termType, c.codeAbbreviation, x.crossRefTerm FROM definitions d
				JOIN terms t ON t.`recordID` = d.`recordID` AND substring(term, 1,1) NOT REGEXP '[A-Z]'
				LEFT OUTER JOIN code c ON c.`code` = d.`code`
				LEFT OUTER JOIN xref x ON x.crossRefID = d.recordID
				WHERE t.termStatus = 'Primary'
				ORDER BY t.term, d.sequence";
		} else {
			$query = sprintf("SELECT t.termID, t.term, t.termStatus, t.termType, t.recordID, d.definition, d.sequence, d.code, d.codeStatus, c.codeAbbreviation, x.crossRefTerm 
				FROM terms t
				 JOIN definitions d ON t.recordID = d.recordID
					LEFT OUTER JOIN code c ON d.code = c.code
				 LEFT OUTER JOIN xref x ON x.crossRefID = t.recordID
				WHERE t.term LIKE '%s%%'
				AND t.termStatus = 'Primary'
				ORDER BY t.term, d.sequence", $value);
		}

		$data = $this->db->query_all($query);
		$newData = $this->transformData( $data, $this->db, $hyperlink );
		return( $newData );
	}

	public function getDefinitionsByCode( $value, $hyperlink = 1 ) {
		$query = sprintf("SELECT t.termID, t.term, t.termStatus, t.termType, t.recordID, d.definition, d.sequence, d.code, d.codeStatus, c.codeAbbreviation, x.crossRefTerm 
			FROM terms t
			 JOIN definitions d ON t.recordID = d.recordID
				LEFT OUTER JOIN code c ON d.code = c.code
			 LEFT OUTER JOIN xref x ON x.crossRefID = t.recordID
			WHERE d.code like '%%%s%%'
			AND t.termStatus = 'Primary'
			ORDER BY t.term, d.sequence", $value);

		$data = $this->db->query_all($query);
		$newData = $this->transformData( $data, $this->db, $hyperlink );
		return( $newData );
	}

	public function getDefinitionsByCodeStatus( $value, $hyperlink=1 ) {
		$query = sprintf("SELECT d.recordID, d.definition, d.sequence, d.code, d.codeStatus, t.termID, t.term, t.termStatus, t.termType, c.codeAbbreviation FROM definitions d
			JOIN terms t ON t.`recordID` = d.`recordID`
			LEFT OUTER JOIN code c ON c.`codeStatus` = d.`codeStatus` 
			WHERE c.codeStatus = '%s'
			ORDER BY t.term, d.sequence", $value);
		$data = $this->db->query_all($query);
		$newData = $this->transformData( $data, $this->db, $hyperlink );
		if ($data == null) $data = array();
		return( $data );
	}

	public function getDefinitionsByTermType( $value, $hyperlink = 1 ) {
		// Do nothing if empty
		if ($value == '') return(array());
		
		$query = sprintf("SELECT d.recordID, d.definition, d.sequence, d.code, d.codeStatus, t.termID, t.term, t.termStatus, t.termType, c.codeAbbreviation FROM definitions d
			JOIN terms t ON t.`recordID` = d.`recordID`
			LEFT OUTER JOIN code c ON c.`code` = d.`code` 
			WHERE t.termType = '%s'
			ORDER BY t.term, d.sequence", $value);
		$data = $this->db->query_all($query);
		$newData = $this->transformData( $data, $this->db, $hyperlink );
		return( $newData );
	}

	public function getDefinitionsByFullText( $value, $highlight = 0 ) {
		// Do nothing if empty
		if ($value == '') return(array());
		
		$query = sprintf("SELECT d.recordID, d.definition, d.sequence, d.code, d.codeStatus, t.termID, t.term, t.termStatus, t.termType, c.codeAbbreviation, CAST((MATCH(definition) AGAINST ('%s' IN BOOLEAN MODE)) AS UNSIGNED ) AS score 
			FROM definitions d
			JOIN terms t ON t.`recordID` = d.`recordID`
			LEFT OUTER JOIN code c ON c.`code` = d.`code` 
			WHERE MATCH(definition) AGAINST ('%s' IN BOOLEAN MODE)
			HAVING score > 0
			ORDER BY score DESC
			LIMIT 100
			", $value, $value);
		$data = $this->db->query_all($query);

		$hyperlink = true;
		$newData = $this->transformData( $data, $this->db, $hyperlink, $value );
		return( $newData );
/*
		if ($data == null) {
			$newData = array();
		} else {
			$tID = -1;
			$newData = array();
			foreach($data as $row) {
				if ($row->termID!= $tID) {
					$row->refLink = BASE_URL . "search/" . urlencode($row->term);
					$newData[] = $row;
				}
				
				if ($highlight) {
					$list = split(" ", $value);
					$i = 0;
					if (is_array( $list)) {
					foreach( $list as $item ) {
						$i++;
						$row->definition = str_ireplace( $item, "<span class=\"highlight" . $i . "\">$item</span>", $row->definition);
					}
					}
				}

				$row->refLink = BASE_URL . "term/" . urlencode($row->term);
				$index = count($newData)-1;
				$newData[$index]->definitions[] = array(
						'def' => $row->definition
					,	'code' => $row->code
					,	'codeStatus' => $row->codeStatus
					,	'codeAbbreviation' => $row->codeAbbreviation
					,	'crossRefTerm' => $row->crossRefTerm
				);
				$newData[$index]->definitionCount = count($newData[$index]->definitions);
				unset($newData[$index]->definition);

				$tID = $row->termID;
			}
		}
		return( $newData );
*/		
	}

	private function transformData( $data, $db, $hyperlink=true, $highlightList = NULL ) {		
		if ($data == null) {
			$newData = array();
		} else {
			$tID = -1;
			$newData = array();
			foreach($data as $row) {

				if ($highlightList != "") {
					$i = 0;
					foreach( split(" ", $highlightList) as $item ) {
						$i++;
						$row->definition = str_ireplace( $item, "<span class=\"highlight" . $i . "\">$item</span>", $row->definition);
					}
				}

				if ($hyperlink) {
					if ($row->codeAbbreviation != '') {					
						$row->definition = str_replace($row->codeAbbreviation, "<a gg:icon=\"iconText\" gg:letter=\"" . $row->code . "\" gg:title=\"Code\" gg:type=\"code\" href=\"#\"><span class=\"code\">" . $row->codeAbbreviation . "</span></a>", $row->definition);
					}
					if ($row->crossRefTerm != '') {
						$row->definition = str_replace($row->crossRefTerm, "<a gg:icon=\"iconText\" gg:letter=\"" . strtoupper(substr($row->crossRefTerm, 0, 1)) . "\" gg:title=\"Term\" gg:type=\"letter\"  gg:id=\"" . $row->crossRefTerm . "\" href=\"#\"><span class=\"code\">" . $row->crossRefTerm . "</span></a>", $row->definition);
					}
					if ($row->code != '') {
						$codes = explode("|", $row->code);
						if (is_array($codes)) {
							$row->code = '';
							foreach($codes as $code) {
								$row->code .= '<a href="#" gg:type="code" gg:title="Code" gg:letter="' . $code . '" gg:icon="iconText"><span class="code">' . $code . '</span></a>, ';
							}
							$row->code = substr($row->code, 0, -2);
						}		
					}
				} else {
					$row->code = str_replace("|", ", ", $row->code);
				}

				if ($row->termID != $tID) {
					$row->refLink = BASE_URL . "term/" . urlencode($row->term);
					$newData[] = $row;
					$index = count($newData)-1;
					$newData[$index]->definitions[] = array(
							'def' => $row->definition
						,	'code' => $row->code
						,	'codeStatus' => $row->codeStatus
						,	'codeAbbreviation' => $row->codeAbbreviation
						,	'crossRefTerm' => $row->crossRefTerm
						,	'sequence' => $row->sequence
					);
					unset($newData[$index]->definition);
					unset($row->sequence);
					$newData[$index]->definitionCount = count($newData[$index]->definitions);
					
					$query = sprintf("SELECT t.term, t.termStatus, t.termType
						FROM terms t
						WHERE t.recordID = %s AND t.termID != %s ORDER BY term", $row->recordID, $row->termID);
					$newData[$index]->related = $this->db->query_all($query);
/*					
					if ($hyperlink && is_array($newData[$index]->related)) {
						foreach($newData[$index]->related as &$r) {
							$r->term = "<a gg:icon=\"iconText\" gg:letter=\"" . strtoupper(substr($r->term, 0, 1)) . "\" gg:title=\"Term\" gg:type=\"letter\"  gg:id=\"" . $r->term . "\" href=\"#\"><span class=\"code\">" . $r->term . "</span></a>";
						}
					}
*/
					if ($newData[$index]->related == null) $newData[$index]->related = array();
					$newData[$index]->relatedCount = count($newData[$index]->related);
				} else {
					$index = count($newData)-1;
					$newData[$index]->definitions[] = array(
							'def' => $row->definition
						,	'code' => $row->code
						,	'codeStatus' => $row->codeStatus
						,	'codeAbbreviation' => $row->codeAbbreviation
						,	'crossRefTerm' => $row->crossRefTerm
						,	'sequence' => $row->sequence
					);
					$newData[$index]->definitionCount = count($newData[$index]->definitions);
				}
				$tID = $row->termID;		
			}
			unset($newData[0]->code);
			unset($newData[0]->codeStatus);
			unset($newData[0]->codeAbbreviation);
		}
		return( $newData );
	}
	
	public function getDefinitionsByTerm( $value, $pattern = 'startswith', $hyperlink = 1 ) {		
		// Do nothing if empty
		if ($value == '') return(array());
		
		switch( $pattern ) {
			default:
			case 'anymatch':
				$value = " LIKE '%" . $value . "%'";
				break;
			case 'startswith':
				$value = " LIKE '" . $value . "%'";
				break;
			case 'endswith':
				$value = " LIKE '%" . $value . "'";
				break;
			case 'exact':
				$value = " = '" . $value . "' ";
				break;
		}

		$query = sprintf("SELECT t.termID, t.term, t.termStatus, t.termType, t.recordID, d.definition, d.sequence, d.code, d.codeStatus, c.codeAbbreviation, x.crossRefTerm 
			FROM terms t
			 JOIN definitions d ON t.recordID = d.recordID
				LEFT OUTER JOIN code c ON d.code = c.code
			 LEFT OUTER JOIN xref x ON x.crossRefID = t.recordID
			WHERE t.term %s
			ORDER BY t.term, d.sequence
			LIMIT 100", $value);
#print $query;
//		$hyperlink = true;
		$data = $this->db->query_all($query);
		$newData = $this->transformData( $data, $this->db, $hyperlink );
		return( $newData );
	}

	private function getAlpha() {
		$alphabet = array('#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
		$list = array();
		foreach( $alphabet as $letter ) {
			$list[] = array(
					'text' => $letter
				,	'leaf' => false
				,	'type' => 'letter'
				, 'iconCls' => 'iconBookOpen'
			);
		}
		return( $list );
	}

	private function getCodeStatus() {
		$query = "SELECT codeStatus as text, true as leaf, 'iconText' AS iconCls, 'codeStatus' AS type FROM codeStatus ORDER BY codeStatus;";
		$data = $this->db->query_all($query);
		if (is_array($data)) {
		foreach($data as &$row) {
			if ($row->termStatus != 'Primary') {
				$row->iconCls = 'iconTextSyn';
			}
		}
		}
		if ($data == null) $data = array();
		return( $data );
	}

	private function getTermType() {
		$query = "SELECT termType as text, 'termType' as type, true as leaf, 'iconText' AS iconCls FROM termType ORDER BY termType;";
		$data = $this->db->query_all($query);
		if ($data == null) $data = array();
		return( $data );
	}

	private function getCode() {
		$query = "SELECT code as text, true as leaf, 'code' AS type, 'iconText' AS iconCls, codeAbbreviation FROM code ORDER BY code;";
		$data = $this->db->query_all($query);
		if ($data == null) $data = array();
		return( $data );
	}

	private function getLetter( $letter ) {
		$query = "SELECT t.*, t2.term AS parentName, t.term as text, 'term' as type, true as leaf, 'iconText' AS iconCls FROM terms t LEFT OUTER JOIN terms t2 ON t2.recordID = t.recordID AND t2.termStatus = 'Primary' ";
		if (isset($letter)) {
			if ($letter == '#') {
				$query .= "WHERE substring(t.term, 1,1) NOT REGEXP '[A-Z]'";
			} else {
				$query .= sprintf("WHERE t.term LIKE '%s%%'"
					, $letter
				);
			}
		}
		$query .= " ORDER BY term LIMIT 500;";

		$data = $this->db->query_all($query);
		if (is_array($data)) {
		foreach($data as &$row) {
			if ($row->termStatus != 'Primary') {
				$row->iconCls = 'iconTextSyn';
				$row->qtip = 'Synonym for: ' . $row->parentName;
			}
		}
		}
		if ($data == null) $data = array();
		return( $data );
	}
	
	private function getRoot() {
		return( array( 
				array(
						'text' => 'Abstract'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'Introduction'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'Scope'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'Acknowledgements'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'The Codes'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'Selected additional sources'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'Selected etymological works'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'Abbreviations'
					,	'leaf' => true
					,	'type' => 'doc'
					,	'iconCls' => 'iconText'
				)
				, array(
						'text' => 'Glossary Terms'
					,	'leaf' => false
					,	'type' => 'terms'
					, 'iconCls' => 'iconBookOpen'
					,	'expanded' => true
					,	'children' => array(
							array(
									'text' => 'Alphabetical List (A-Z)'
								,	'leaf' => false
								, 'iconCls' => 'iconBookOpen'
								,	'type' => 'alpha'
							)
						)
				)
				, array(
						'text' => 'Code'
					, 'iconCls' => 'iconBookOpen'
					,	'leaf' => false
					,	'type' => 'code'
				)
				, array(
						'text' => 'Term Type'
					, 'iconCls' => 'iconBookOpen'
					,	'leaf' => false
					,	'type' => 'termType'
				)
/*				
				, array(
						'text' => 'Code Status'
					, 'iconCls' => 'iconBookOpen'
					,	'leaf' => false
					,	'type' => 'codeStatus'
				)
*/				
			) 
		);
	}
	
}
?>